package com.hspedu.seckill.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hspedu.seckill.mapper.OrderMapper;
import com.hspedu.seckill.mapper.SeckillGoodsMapper;
import com.hspedu.seckill.mapper.SeckillOrderMapper;
import com.hspedu.seckill.pojo.Order;
import com.hspedu.seckill.pojo.SeckillGoods;
import com.hspedu.seckill.pojo.SeckillOrder;
import com.hspedu.seckill.pojo.User;
import com.hspedu.seckill.service.OrderService;
import com.hspedu.seckill.service.SeckillGoodsService;
import com.hspedu.seckill.util.MD5Util;
import com.hspedu.seckill.util.UUIDUtil;
import com.hspedu.seckill.vo.GoodsVo;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private SeckillGoodsService seckillGoodsService;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private SeckillOrderMapper seckillOrderMapper;

    @Resource
    private RedisTemplate redisTemplate;


    //秒杀方法
    @Override
    @Transactional
    public Order seckill(User user, GoodsVo goodsVo) {
        Long goodsId = goodsVo.getId();
        Long userId = user.getId();


        boolean update = seckillGoodsService.update(new UpdateWrapper<SeckillGoods>()
                .setSql("stock_count = stock_count - 1")
                .gt("stock_count", 0)
                .eq("goods_id", goodsId));
        if (!update) {
            //秒杀失败，将秒杀结果存入redis
            redisTemplate.opsForValue().set("secKillResult:" + userId + ":" + goodsId, -1);
            return null;
        }

        //生成订单
        Order order = new Order();

        order.setUserId(user.getId());
        order.setGoodsId(goodsId);
        order.setDeliveryAddrId(0L);//设置默认值
        order.setGoodsName(goodsVo.getGoodsName());
        order.setGoodsCount(1);
        order.setGoodsPrice(goodsVo.getSeckillPrice());
        order.setOrderChannel(1);
        order.setStatus(0);
        order.setCreateDate(new Date());
        order.setPayDate(new Date());//设置默认值
        orderMapper.insert(order);

        //生成秒杀订单
        SeckillOrder seckillOrder = new SeckillOrder();
        seckillOrder.setGoodsId(goodsId);
        seckillOrder.setUserId(user.getId());
        seckillOrder.setOrderId(order.getId());
        seckillOrderMapper.insert(seckillOrder);

        //将生成的秒杀订单，存入到redis，这样在查询   某个用户是否已经秒杀了这个商品时直接到redis中查询，起到优化效果
        //设计秒杀订单的key => order:用户id:商品id
        redisTemplate.opsForValue().set("order:" + userId + ":" + goodsId, seckillOrder);

        //秒杀成功，将秒杀订单号存入redis
        redisTemplate.opsForValue().set("secKillResult:" + userId + ":" + goodsId, order.getId());
        return order;
    }


    //生成秒杀唯一秒杀路径
    @Override
    public String createPath(User user, Long goodsId) {
        String path = MD5Util.md5(UUIDUtil.uuid());
        //将秒杀路径存放到redis
        redisTemplate.opsForValue().set("seckillPath:" + user.getId() + ":" + goodsId, path, 60, TimeUnit.SECONDS);
        return path;
    }


    //对秒杀路径进行校验
    @Override
    public boolean checkPath(User user, Long goodsId, String path) {
        String redisPath = (String) redisTemplate.opsForValue().get("seckillPath:" + user.getId() + ":" + goodsId);
        return path.equals(redisPath);
    }


    //验证用户输入的验证码是否正确
    @Override
    public boolean checkCaptcha(User user, Long goodsId, String captcha) {
        //取出redis的验证码
        String redisCaptcha = (String)redisTemplate.opsForValue().get("captcha:" + user.getId() + ":" + goodsId);

        if (StringUtils.hasText(redisCaptcha)){
            return redisCaptcha.equals(captcha);
        }

        return false;
    }
}
